package com.yungu.swift.assets.driver.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import com.yungu.swift.assets.consts.BankConst;
import com.yungu.swift.assets.driver.dao.DriverCashMapper;
import com.yungu.swift.assets.driver.dao.DriverMapper;
import com.yungu.swift.assets.driver.model.dto.DriverCashDto;
import com.yungu.swift.assets.driver.model.dto.DriverDto;
import com.yungu.swift.assets.driver.model.dto.DriverWithdrawalDto;
import com.yungu.swift.assets.driver.model.param.AdminDriverCashBillPageParam;
import com.yungu.swift.assets.driver.model.param.AdminDriverCashParam;
import com.yungu.swift.assets.driver.service.DriverCashService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.mapper.IMapper;
import com.yungu.swift.base.model.PageVo;
import com.yungu.swift.base.model.admin.AdminUuidParam;
import com.yungu.swift.base.service.impl.BaseServiceImpl;
import com.yungu.swift.constants.FinanceConstant;
import com.yungu.swift.constants.MagicConstant;
import com.yungu.swift.order.service.AliPayCashService;
import com.yungu.swift.order.service.CashService;
import com.yungu.swift.order.service.WxPayCashService;
import com.yungu.swift.order.service.WxToBankService;
import com.yungu.swift.system.finance.model.dto.FinanceWithdrawalDto;
import com.yungu.swift.system.finance.service.FinanceWithdrawalService;
import com.yungu.swift.system.sys.model.dto.SysAccountDriverDto;
import com.yungu.swift.system.sys.model.dto.SysAccountPlatformDto;
import com.yungu.swift.system.sys.service.SysAccountDriverService;
import com.yungu.swift.system.sys.service.SysAccountPlatformService;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.ParamUtil;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.yungu.swift.assets.driver.model.dto.DriverCashDto.CHECK_STATUS_FAILURE;
import static com.yungu.swift.assets.driver.model.dto.DriverCashDto.CHECK_STATUS_SUCCESS;

/**
 * 司机提现业务逻辑接口实现类
 *
 * @author cuixiuyin
 * @version 1.1.1-SNAPSHOT
 * @since 2019-08-17 16:23
 */
@Slf4j
@Service
public class DriverCashServiceImpl extends BaseServiceImpl<DriverCashDto> implements DriverCashService {

    @Autowired
    private DriverCashMapper driverCashMapper;
    @Autowired
    private DriverMapper driverMapper;
    @Autowired
    private TransactionTemplate transactionTemplate;

    @Reference
    private SysAccountDriverService sysAccountDriverService;
    @Reference
    private FinanceWithdrawalService financeWithdrawalService;
    @Reference
    private SysAccountPlatformService sysAccountPlatformService;
    @Reference
    private WxToBankService wxToBankService;
    @Reference
    private AliPayCashService aliPayCashService;
    @Reference
    private WxPayCashService wxPayCashService;

    @Override
    protected IMapper<DriverCashDto> getMapper() {
        return driverCashMapper;
    }

    @Override
    public ResponseData<Boolean> addCash(String uuid, Integer collectType, String collectAccount, Double cash, Double poundage) {
        //提取金额（用于记录流水）
        BigDecimal bigDecimalCash = BigDecimal.valueOf(cash);
        //手续费（用于记录流水）
        BigDecimal bigDecimalPoundage = BigDecimal.valueOf(poundage);
        // 1.司机账户信息
        ResponseData<SysAccountDriverDto> getAccountDriver = sysAccountDriverService.get(uuid);
        if (!getAccountDriver.isSuccess() && getAccountDriver.getData() != null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机提现账户不存在");
        }
        SysAccountDriverDto sysAccountDriverDto = getAccountDriver.getData();
        //司机可提现余额（用于记录流水）
        BigDecimal canFrowardBalance = sysAccountDriverDto.getCanFrowardBalance();
        //判断司机提现金额+手续费不得超过司机可提现金额
        BigDecimal totol = bigDecimalCash.add(bigDecimalPoundage);
        if (totol.compareTo(canFrowardBalance) > 0) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "提现失败，提现金额超过可提现余额");
        }
        // 2.司机信息
        DriverDto driverDto = driverMapper.list(MapUtils.build("uuid", uuid)).get(0);
        // 3.平台账户信息
        ResponseData<List<SysAccountPlatformDto>> getAccountPlatform = sysAccountPlatformService.list(MapUtils.build());
        if (!getAccountPlatform.isSuccess() && CollectionUtils.isNotEmpty(getAccountPlatform.getData())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取平台账户信息失败");
        }
        SysAccountPlatformDto sysAccountPlatformDto = getAccountPlatform.getData().get(0);
        Date nowDate = new Date();

        //1. 增加提现记录到driverCash表
        DriverCashDto driverCashDto = new DriverCashDto();
        driverCashDto.setUuid(StringUtils.buildUUID());
        driverCashDto.setAppid(driverDto.getAppid());
        driverCashDto.setUserUuid(uuid);
        driverCashDto.setCash(cash);
        driverCashDto.setStatus(DriverCashDto.UNDER_CHECK_STATUS);
        driverCashDto.setCollectAccount(collectAccount);
        //开户行（提现到银行卡）
        String bankName = null;
        if (collectType == MagicConstant.INT_ONE && (bankName = BankConst.getName(collectAccount)) == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到该银行卡的开户行");
        }
        driverCashDto.setCollectBankName(bankName);
        driverCashDto.setCollectName(driverDto.getName());
        driverCashDto.setCollectType(collectType);
        driverCashDto.setCreateOn(nowDate);
        driverCashDto.setPoundage(poundage);
//        driverCashDto.setActualAmount(BigDecimal.valueOf(cash - poundage).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue());
        driverCashDto.setActualAmount(BigDecimal.valueOf(cash - poundage).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());

        // 2.记录手续费财务流水
        FinanceWithdrawalDto financeHandlingFeeDto = new FinanceWithdrawalDto();
        if (null != poundage && poundage > 0) {
            // 司机提取金额扣除手续费
            bigDecimalCash = bigDecimalCash.subtract(bigDecimalPoundage);
            financeHandlingFeeDto.setUuid(StringUtils.buildUUID());
            financeHandlingFeeDto.setAppid(driverDto.getAppid());
            financeHandlingFeeDto.setFinanceNumber(StringUtils.buildUUID());
            //司机提现表uuid
            financeHandlingFeeDto.setBusinessUuid(driverCashDto.getUuid());
            //资金流出方
            financeHandlingFeeDto.setFinanceOutflow(sysAccountDriverDto.getUuid());
            //资金流入方
            financeHandlingFeeDto.setFinanceInflow(sysAccountPlatformDto.getUuid());
            //发生额
            financeHandlingFeeDto.setAmount(bigDecimalPoundage);
            //科目4004
            financeHandlingFeeDto.setCourse(FinanceConstant.WITHDRAWAL_POUNDAGE);
            //发生日期
            financeHandlingFeeDto.setHappenTime(nowDate);
            //期初余额 = 司机可提现金额
            financeHandlingFeeDto.setStartBalance(canFrowardBalance);
            //期末金额 = 司机可提现金额 - 手续费
            canFrowardBalance = canFrowardBalance.subtract(bigDecimalPoundage);
            financeHandlingFeeDto.setFinalBalance(canFrowardBalance);
            financeHandlingFeeDto.setDescription(String.format("司机 %s 提现申请手续费 %s 元支出到平台", driverDto.getName(), bigDecimalPoundage));
            financeHandlingFeeDto.setStatus(null);
            financeHandlingFeeDto.setCreateBy(uuid);
            financeHandlingFeeDto.setCreateOn(nowDate);
        }

        //3、插入提现流水表（不包括手续费）
        FinanceWithdrawalDto financeWithdrawalDto = new FinanceWithdrawalDto();
        financeWithdrawalDto.setUuid(StringUtils.buildUUID());
        financeWithdrawalDto.setAppid(driverDto.getAppid());
        financeWithdrawalDto.setFinanceNumber(StringUtils.buildUUID());
        financeWithdrawalDto.setBusinessUuid(driverCashDto.getUuid());
        financeWithdrawalDto.setFinanceOutflow(sysAccountDriverDto.getUuid());
        financeWithdrawalDto.setFinanceInflow(sysAccountPlatformDto.getUuid());
        financeWithdrawalDto.setAmount(bigDecimalCash);
        //科目编码
        Integer course = FinanceConstant.WITHDRAWAL_TO_BANK_CARD;
        if (collectType == MagicConstant.INT_TWO) {
            course = FinanceConstant.WITHDRAWAL_TO_TEN;
        }
        if (collectType == MagicConstant.INT_THREE) {
            course = FinanceConstant.WITHDRAWAL_TO_ALI;
        }
        financeWithdrawalDto.setCourse(course);
        financeWithdrawalDto.setHappenTime(nowDate);
        financeWithdrawalDto.setStartBalance(canFrowardBalance);
        canFrowardBalance = canFrowardBalance.subtract(bigDecimalCash);
        financeWithdrawalDto.setFinalBalance(canFrowardBalance);
        financeWithdrawalDto.setDescription(String.format("司机 %s 提现申请 %s 元支出到平台", driverDto.getName(), bigDecimalCash));
        financeWithdrawalDto.setStatus(null);
        financeWithdrawalDto.setCreateBy(uuid);
        financeWithdrawalDto.setCreateOn(new Date());

        //4. 更新司机账户
        sysAccountDriverDto.setFrowardAccumulate(BigDecimal.valueOf(cash).add(ParamUtil.defaultIfNull(sysAccountDriverDto
                .getFrowardAccumulate(), BigDecimal.valueOf(0.0))));
        //可提现余额
        sysAccountDriverDto.setCanFrowardBalance(sysAccountDriverDto.getCanFrowardBalance().subtract(BigDecimal.valueOf(cash)));
        sysAccountDriverDto.setUpdateOn(nowDate);

        //5. 更新平台账户表
        sysAccountPlatformDto.setCashBalance(sysAccountPlatformDto.getCashBalance().add(BigDecimal.valueOf(cash)));
        sysAccountPlatformDto.setUpdateOn(nowDate);

        transactionTemplate.execute(transactionStatus -> {
            if (driverCashMapper.add(driverCashDto) > 0) {
                log.info("1. 司机（{}）提现插入提现表成功", uuid);
            }
            if (StringUtils.isNotEmpty(financeHandlingFeeDto.getUuid()) && financeWithdrawalService.add(
                    financeHandlingFeeDto).isSuccess()) {
                log.info("2. 司机（{}）提现手续费流水插入成功", uuid);
            }
            if (financeWithdrawalService.add(financeWithdrawalDto).isSuccess()) {
                log.info("3. 司机（{}）提现金额流水插入成功", uuid);
            }
            if (sysAccountDriverService.edit(sysAccountDriverDto).isSuccess()) {
                log.info("4. 司机（{}）提现更新司机账户成功", uuid);
            }
            if (sysAccountPlatformService.edit(sysAccountPlatformDto).isSuccess()) {
                log.info("5. 司机（{}）提现更新平台账户成功", uuid);
            }
            return Boolean.TRUE;
        });
        return ResponseData.buildSuccessResponse("提现申请提交成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> reviewCash(AdminDriverCashParam driverCashParam) {
        //获取司机提现申请记录
        DriverCashDto cashDto = driverCashMapper.list(MapUtils.build("uuid", driverCashParam.getUuid())).get(0);
        if (cashDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获得不到司机提现信息");
        }
        // 1. 更新司机提现表
        DriverCashDto cashUpdateDto = new DriverCashDto();
        BeanUtils.copyProperties(driverCashParam, cashUpdateDto);
        cashUpdateDto.setUserUuid(null);
        cashUpdateDto.setUpdateOn(new Date());
        cashUpdateDto.setUpdateBy(driverCashParam.getUserUuid());
        cashUpdateDto.setHandlingBy(driverCashParam.getUserUuid());
        cashUpdateDto.setHandlingOn(new Date());

        // 当状态为审核成功的时候
        if (CHECK_STATUS_SUCCESS == driverCashParam.getStatus()) {
            //修改提现状态为提现中
            cashUpdateDto.setWithdrawalStatus(DriverCashDto.UNDER_WITHDRAWAL_STATUS);
            if (driverCashMapper.edit(cashUpdateDto) > 0) {
                log.info("1. 更新司机提现信息成功，uuid:{}", cashDto.getUserUuid());
            }
            return ResponseData.buildSuccessResponse("修改司机提现申请状态成功", Boolean.TRUE);
        }
        //如果审核失败，则将提现的金额退回司机余额账户
        if (CHECK_STATUS_FAILURE == driverCashParam.getStatus()) {
            //修改提现状态为提现失败
            cashUpdateDto.setWithdrawalStatus(DriverCashDto.WITHDRAWAL_STATUS_FAILURE);
            return reviewFailure(cashDto, cashUpdateDto);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机提现审核失败");
    }

    private ResponseData<Boolean> reviewFailure(DriverCashDto cashDto, DriverCashDto cashUpdateDto) {
        //司机信息
        DriverDto driverDto = driverMapper.list(MapUtils.build("uuid", cashDto.getUserUuid())).get(0);
        if (driverDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机信息");
        }
        //司机账户信息
        SysAccountDriverDto sysAccountDriverDto = sysAccountDriverService.get(driverDto.getUuid()).getData();
        if (sysAccountDriverDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机账户信息");
        }
        //获取平台账户信息
        List<SysAccountPlatformDto> list = sysAccountPlatformService.list(MapUtils.build("appid", cashDto.getAppid())).getData();
        if (CollectionUtils.isEmpty(list)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到平台账户信息");
        }
        SysAccountPlatformDto sysAccountPlatformDto = list.get(0);

        //司机可提现余额
        BigDecimal canFrowardBalance = sysAccountDriverDto.getCanFrowardBalance();
        //平台余额
        BigDecimal cashBalance = sysAccountPlatformDto.getCashBalance();
        Date now = new Date();

        //手续费流水
        FinanceWithdrawalDto financeHandlingFeeDto = new FinanceWithdrawalDto();
        if (null != cashDto.getPoundage() && cashDto.getPoundage() > 0) {
            financeHandlingFeeDto.setUuid(StringUtils.buildUUID());
            financeHandlingFeeDto.setAppid(driverDto.getAppid());
            financeHandlingFeeDto.setFinanceNumber(StringUtils.buildUUID());
            //司机提现表uuid
            financeHandlingFeeDto.setBusinessUuid(cashDto.getUuid());
            //资金流出方
            financeHandlingFeeDto.setFinanceOutflow(sysAccountDriverDto.getUuid());
            //资金流入方
            financeHandlingFeeDto.setFinanceInflow(sysAccountDriverDto.getUuid());
            //发生额
            financeHandlingFeeDto.setAmount(BigDecimal.valueOf(cashDto.getPoundage()));
            //科目
            financeHandlingFeeDto.setCourse(FinanceConstant.WITHDRAWAL_BACK_POUNDAGE);
            //发生日期
            financeHandlingFeeDto.setHappenTime(now);
            //期初余额
            financeHandlingFeeDto.setStartBalance(canFrowardBalance);
            //期末余额
            canFrowardBalance = canFrowardBalance.add(BigDecimal.valueOf(cashDto.getPoundage()));
            financeHandlingFeeDto.setFinalBalance(canFrowardBalance);
            financeHandlingFeeDto.setDescription(String.format("司机 %s 提现申请拒绝手续费 %s 元退回账户", driverDto.getName(), cashDto.getPoundage()));
            financeHandlingFeeDto.setStatus(null);
        }
        // 实际到账金额流水
        FinanceWithdrawalDto financeWithdrawalDto = new FinanceWithdrawalDto();
        financeWithdrawalDto.setUuid(StringUtils.buildUUID());
        financeWithdrawalDto.setAppid(driverDto.getAppid());
        financeWithdrawalDto.setFinanceNumber(StringUtils.buildUUID());
        financeWithdrawalDto.setBusinessUuid(cashDto.getUuid());
        //资金流出方
        financeWithdrawalDto.setFinanceOutflow(sysAccountPlatformDto.getUuid());
        //资金流入方
        financeWithdrawalDto.setFinanceInflow(sysAccountDriverDto.getUuid());
        financeWithdrawalDto.setAmount(BigDecimal.valueOf(cashDto.getActualAmount()));
        //科目
        Integer course = null;
        switch (cashDto.getCollectType()) {
            case 1:
                course = FinanceConstant.WITHDRAWAL_BACK_BANK_CARD;
                break;
            case 2:
                course = FinanceConstant.WITHDRAWAL_BACK_TEN;
                break;
            case 3:
                course = FinanceConstant.WITHDRAWAL_BACK_ALI;
                break;
            default:
                break;
        }
        financeWithdrawalDto.setCourse(course);
        //发生日期
        financeWithdrawalDto.setHappenTime(now);
        //期初余额
        financeWithdrawalDto.setStartBalance(canFrowardBalance);
        //期末余额
        canFrowardBalance = canFrowardBalance.add(BigDecimal.valueOf(cashDto.getActualAmount()));
        financeWithdrawalDto.setFinalBalance(canFrowardBalance);
        financeWithdrawalDto.setDescription(String.format("司机 %s 提现申请拒绝 %s 元退回账户", driverDto.getName(), cashDto.getActualAmount()));
        financeWithdrawalDto.setStatus(null);

        //更新司机账户表
        //提现累计
        BigDecimal frowardAccumulate = sysAccountDriverDto.getFrowardAccumulate().subtract(BigDecimal.valueOf(cashDto.getCash()));
        sysAccountDriverDto.setFrowardAccumulate(frowardAccumulate);
        sysAccountDriverDto.setCanFrowardBalance(canFrowardBalance);
        sysAccountDriverDto.setUpdateOn(now);

        //更新平台账户表
        cashBalance = cashBalance.subtract(BigDecimal.valueOf(cashDto.getCash()));
        sysAccountPlatformDto.setCashBalance(cashBalance);
        sysAccountPlatformDto.setUpdateOn(now);
        sysAccountPlatformService.edit(sysAccountPlatformDto);

        transactionTemplate.execute(transactionStatus -> {
            if (driverCashMapper.edit(cashUpdateDto) > 0) {
                log.info("1. 司机（{}）提现审核失败，更新提现表成功", cashDto.getUserUuid());
            }
            if (StringUtils.isNotEmpty(financeHandlingFeeDto.getUuid()) && financeWithdrawalService.add(
                    financeHandlingFeeDto).isSuccess()) {
                log.info("2. 司机（{}）提现审核失败，手续费退回流水插入成功", cashDto.getUserUuid());
            }
            ResponseData<Boolean> editFinanceWithdrawal = financeWithdrawalService.add(financeWithdrawalDto);
            if (editFinanceWithdrawal.isSuccess() && Boolean.TRUE.equals(editFinanceWithdrawal.getData())) {
                log.info("3. 司机（{}）提现审核失败，金额流水插入成功", cashDto.getUserUuid());
            }
            ResponseData<Boolean> editSysAccountDriver = sysAccountDriverService.edit(sysAccountDriverDto);
            if (editSysAccountDriver.isSuccess() && Boolean.TRUE.equals(editSysAccountDriver.getData())) {
                log.info("4. 司机（{}）提现审核失败，更新司机账户成功", cashDto.getUserUuid());
            }
            ResponseData<Boolean> editAccountPlaform = sysAccountPlatformService.edit(sysAccountPlatformDto);
            if (editAccountPlaform.isSuccess() && Boolean.TRUE.equals(editAccountPlaform.getData())) {
                log.info("5. 司机（{}）提现审核失败，更新平台账户成功", cashDto.getUserUuid());
            }
            return Boolean.TRUE;
        });
        return ResponseData.buildSuccessResponse("修改司机提现申请状态成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<PageVo<DriverWithdrawalDto>> cashBillPage(AdminDriverCashBillPageParam cashOutPageParam) {
        PageBounds pageBounds = new PageBounds(cashOutPageParam.getPageNum(), cashOutPageParam.getPageSize());
        PageList<DriverWithdrawalDto> pageList = driverCashMapper.cashBillPage(BeanMap.create(cashOutPageParam), pageBounds);
        PageVo<DriverWithdrawalDto> pageVo = new PageVo(cashOutPageParam.getPageNum(), cashOutPageParam.getPageSize(),
                pageList.getPaginator().getTotalCount());
        pageVo.setItems(pageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    @Override
    public ResponseData<List<DriverWithdrawalDto>> cashBillExport(AdminDriverCashBillPageParam cashOutPageParam) {
        return ResponseData.buildSuccessResponse(driverCashMapper.cashBillPage(BeanMap.create(cashOutPageParam)));
    }

    /**
     * 提现打款操作
     *
     * @param driverCashParam
     * @return
     */
    @Override
    public ResponseData<Boolean> remit(AdminDriverCashParam driverCashParam) {
        //获取司机提现申请记录
        DriverCashDto cashDto = driverCashMapper.list(MapUtils.build("uuid", driverCashParam.getUuid())).get(0);
        if (cashDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获得不到司机提现信息");
        }
        if (cashDto.getThirdPayStatus() != null && DriverCashDto.THIRD_STATUS_PROCESSING == cashDto.getThirdPayStatus()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "正在打款中，请稍后刷新查看结果");
        }
        if (cashDto.getThirdPayStatus() != null && DriverCashDto.THIRD_STATUS_SUCCESS == cashDto.getThirdPayStatus()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "已打款成功，请勿重复操作");
        }
        if (cashDto.getThirdPayStatus() != null && DriverCashDto.THIRD_STATUS_FAILURE == cashDto.getThirdPayStatus()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "打款失败，原因是" + cashDto.getThirdReason());
        }
        // 1. 更新司机提现表
        DriverCashDto cashUpdateDto = new DriverCashDto();
        cashUpdateDto.setUserUuid(null);
        cashUpdateDto.setUpdateOn(new Date());
        cashUpdateDto.setUpdateBy(driverCashParam.getUserUuid());
        cashUpdateDto.setHandlingBy(driverCashParam.getUserUuid());
        cashUpdateDto.setHandlingOn(new Date());
        cashUpdateDto.setSerialNum(driverCashParam.getSerialNum());
        cashUpdateDto.setUuid(driverCashParam.getUuid());
        //修改第三方打款状态为处理中
        cashUpdateDto.setThirdPayStatus(DriverCashDto.THIRD_STATUS_PROCESSING);

        // 打款类型是到银行卡 要走自动打款操作
        if (cashDto.getCollectType() == MagicConstant.INT_ONE) {
            return remitToBank(cashDto, cashUpdateDto);
        }
        // 打款类型是支付宝
        if (cashDto.getCollectType() == MagicConstant.INT_THREE) {
            return remitToAccount(aliPayCashService, cashDto, cashUpdateDto);
        }
        // 打款类型是微信
        if (cashDto.getCollectType() != MagicConstant.INT_ONE) {
            return remitToAccount(wxPayCashService, cashDto, cashUpdateDto);
        }
        return ResponseData.buildErrorResponse(0, "操作类型异常");
    }


    @Override
    public ResponseData<Boolean> repay(AdminUuidParam adminUuidParam) {
        //获取司机提现申请记录
        DriverCashDto cashDto = driverCashMapper.list(MapUtils.build("uuid", adminUuidParam.getUuid())).get(0);
        if (cashDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获得不到司机提现信息");
        }
        // 1. 更新司机提现表
        DriverCashDto cashUpdateDto = new DriverCashDto();
        cashUpdateDto.setUserUuid(null);
        cashUpdateDto.setUpdateOn(new Date());
        cashUpdateDto.setUpdateBy(adminUuidParam.getUserUuid());
        cashUpdateDto.setHandlingBy(adminUuidParam.getUserUuid());
        cashUpdateDto.setHandlingOn(new Date());
        // 重新生成新的流水号
        cashUpdateDto.setSerialNum(System.currentTimeMillis() + "");
        cashUpdateDto.setUuid(adminUuidParam.getUuid());
        //修改第三方打款状态为处理中
        cashUpdateDto.setThirdPayStatus(DriverCashDto.THIRD_STATUS_PROCESSING);

        // 打款类型是到银行卡
        if (cashDto.getCollectType() == MagicConstant.INT_ONE) {
            return remitToBank(cashDto, cashUpdateDto);
        }
        // 打款类型是支付宝
        if (cashDto.getCollectType() == MagicConstant.INT_THREE) {
            return remitToAccount(aliPayCashService, cashDto, cashUpdateDto);
        }
        // 打款类型是微信
        if (cashDto.getCollectType() != MagicConstant.INT_ONE) {
            return remitToAccount(wxPayCashService, cashDto, cashUpdateDto);
        }
        return ResponseData.buildErrorResponse(0, "操作类型异常");
    }


    @Override
    public ResponseData<Boolean> cancelPay(AdminUuidParam uuidParam) {
        DriverCashDto driverCashDto = driverCashMapper.list(MapUtils.build("uuid", uuidParam.getUuid())).get(0);
        if (driverCashDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机提现信息");
        }
        if (driverCashDto.getThirdPayStatus() != null && DriverCashDto.THIRD_STATUS_PROCESSING == driverCashDto.getThirdPayStatus()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "第三方平台正在打款中，请等待打款结果");
        }
        //修改提现状态为提现失败
        driverCashDto.setThirdPayStatus(DriverCashDto.THIRD_STATUS_FAILURE);
        driverCashDto.setWithdrawalStatus(DriverCashDto.WITHDRAWAL_STATUS_FAILURE);
        driverCashDto.setUpdateOn(new Date());
        driverCashDto.setUpdateBy(uuidParam.getUserUuid());
        driverCashMapper.edit(driverCashDto);

        //获取平台账户信息
        ResponseData<SysAccountPlatformDto> getPlatformAccount = sysAccountPlatformService.getByAppid(driverCashDto.getAppid());
        if (!getPlatformAccount.isSuccess() || getPlatformAccount.getData() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到平台账户信息");
        }
        SysAccountPlatformDto sysAccountPlatformDto = getPlatformAccount.getData();

        //获取司机账户信息
        ResponseData<SysAccountDriverDto> getDriverAccount = sysAccountDriverService.get(driverCashDto.getUserUuid());
        if (!getDriverAccount.isSuccess() || getDriverAccount.getData() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机账户信息");
        }
        SysAccountDriverDto sysAccountDriverDto = getDriverAccount.getData();

        //记录司机提现金额退款流水
        //提现实际到账金额
        BigDecimal amount = BigDecimal.valueOf(driverCashDto.getActualAmount());
        //司机期末可提现余额
        BigDecimal canFrowardBalance = sysAccountDriverDto.getCanFrowardBalance();
        FinanceWithdrawalDto financeWithdrawalDto = new FinanceWithdrawalDto();
        financeWithdrawalDto.setFinanceNumber(StringUtils.buildUUID());
        financeWithdrawalDto.setHappenTime(new Date());
        financeWithdrawalDto.setUuid(StringUtils.buildUUID());
        financeWithdrawalDto.setAmount(amount);
        //科目
        Integer course = null;
        switch (driverCashDto.getCollectType()) {
            case 1:
                course = FinanceConstant.WITHDRAWAL_BACK_BANK_CARD;
                break;
            case 2:
                course = FinanceConstant.WITHDRAWAL_BACK_TEN;
                break;
            case 3:
                course = FinanceConstant.WITHDRAWAL_BACK_ALI;
                break;
            default:
                break;
        }
        financeWithdrawalDto.setCourse(course);
        financeWithdrawalDto.setBusinessUuid(driverCashDto.getUuid());
        //资金流出方
        financeWithdrawalDto.setFinanceOutflow(sysAccountPlatformDto.getUuid());
        //资金流入方
        financeWithdrawalDto.setFinanceInflow(sysAccountDriverDto.getUuid());
        financeWithdrawalDto.setStartBalance(canFrowardBalance);
        canFrowardBalance = canFrowardBalance.add(amount);
        financeWithdrawalDto.setFinalBalance(canFrowardBalance);
        financeWithdrawalDto.setDescription("平台取消打款，退回提现实际到账金额" + amount + "元到司机账户");
        financeWithdrawalDto.setCreateOn(new Date());
        financeWithdrawalDto.setCreateBy(uuidParam.getUserUuid());
        financeWithdrawalService.add(financeWithdrawalDto);

        //如果存在提现手续费 则记录提现手续费退款流水
        if (driverCashDto.getPoundage() != null && driverCashDto.getPoundage() > 0) {
            //手续费
            BigDecimal poundage = BigDecimal.valueOf(driverCashDto.getPoundage());
            FinanceWithdrawalDto driverWithdrawalDto = new FinanceWithdrawalDto();
            driverWithdrawalDto.setFinanceNumber(StringUtils.buildUUID());
            driverWithdrawalDto.setHappenTime(new Date());
            driverWithdrawalDto.setUuid(StringUtils.buildUUID());
            driverWithdrawalDto.setAmount(poundage);

            financeWithdrawalDto.setCourse(FinanceConstant.WITHDRAWAL_BACK_POUNDAGE);
            driverWithdrawalDto.setBusinessUuid(driverCashDto.getUuid());
            //资金流出方
            driverWithdrawalDto.setFinanceOutflow(sysAccountPlatformDto.getUuid());
            //资金流入方
            driverWithdrawalDto.setFinanceInflow(sysAccountDriverDto.getUuid());
            driverWithdrawalDto.setStartBalance(canFrowardBalance);
            canFrowardBalance = canFrowardBalance.add(poundage);
            driverWithdrawalDto.setFinalBalance(canFrowardBalance);
            driverWithdrawalDto.setDescription("平台取消打款，退回提现手续费" + poundage + "元到司机账户");

            driverWithdrawalDto.setCreateOn(new Date());
            driverWithdrawalDto.setCreateBy(uuidParam.getUserUuid());
            financeWithdrawalService.add(driverWithdrawalDto);
        }
        //保存司机账户信息
        sysAccountDriverDto.setCanFrowardBalance(canFrowardBalance);
        sysAccountDriverDto.setUpdateBy(uuidParam.getUserUuid());
        sysAccountDriverDto.setUpdateOn(new Date());
        sysAccountDriverService.edit(sysAccountDriverDto);

        //保存平台账户信息
        sysAccountPlatformDto.setCashBalance(sysAccountPlatformDto.getCashBalance().subtract(BigDecimal.valueOf(driverCashDto.getCash())));
        sysAccountPlatformDto.setUpdateBy(uuidParam.getUserUuid());
        sysAccountPlatformDto.setUpdateOn(new Date());
        sysAccountPlatformService.edit(sysAccountPlatformDto);
        return ResponseData.buildSuccessResponse("取消打款成功", Boolean.TRUE);
    }

    /**
     * 打款到银行卡
     *
     * @param cashDto
     * @param cashUpdateDto
     * @return
     */
    private ResponseData<Boolean> remitToBank(DriverCashDto cashDto, DriverCashDto cashUpdateDto) {
        boolean edit = driverCashMapper.edit(cashUpdateDto) > 0;
        if (edit) {
            log.info("1. 司机（{}）更新信息成功，开始银行卡打款操作", cashDto.getUserUuid());
            //自动打款 —— 金额为司机实际到账金额 单位为元需要转换成分
            ResponseData<Map<String, String>> responseData = wxToBankService.wxToBank(cashDto.getCollectAccount(),
                    cashDto.getCollectName(), cashDto.getCollectBankName(), new Double(cashDto.getActualAmount()
                            * 100).intValue(), cashUpdateDto.getSerialNum());
            if (!responseData.isSuccess() || responseData.getData() == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, responseData.getMsg());
            }
            log.info("1. 司机（{}）结束银行卡打款操作", cashDto.getUserUuid());
        } else {
            log.error("1. 司机（{}）更新信息失败", cashDto.getUserUuid());
        }
        return ResponseData.buildSuccessResponse("修改司机打款操作成功", Boolean.TRUE);
    }


    /**
     * 打款到支付宝/微信
     *
     * @param cashDto
     * @param cashUpdateDto
     * @return
     */
    private ResponseData<Boolean> remitToAccount(CashService cashService, DriverCashDto cashDto, DriverCashDto cashUpdateDto) {
        boolean edit = driverCashMapper.edit(cashUpdateDto) > 0;
        if (edit) {
            log.info("1. 司机（{}）更新信息成功，开始打款操作", cashDto.getUserUuid());
            ResponseData<Map<String, String>> toAccount = cashService.toAccount(cashDto.getCollectName(),
                    cashDto.getCollectAccount(), cashDto.getActualAmount(), cashUpdateDto.getSerialNum());
            if (!toAccount.isSuccess() || toAccount.getData() == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, toAccount.getMsg());
            }
            log.info("1. 司机（{}）结束打款操作", cashDto.getUserUuid());
        } else {
            log.error("1. 司机（{}）更新信息失败", cashDto.getUserUuid());
        }
        return ResponseData.buildSuccessResponse("修改司机打款操作成功", Boolean.TRUE);
    }
}
